#include "TcpServer.hpp"
//#include "CommandExec.hpp"
#include "Protocol.hpp"
#include "Calculator.hpp"
#include "Deamon.hpp"
#include <memory>

using namespace LogModule;

//封装器, 可调用对象 参数为一个Request类对象, 返回值类型Response
using cal_fun = std::function<Response(const Request &req)>;

class Parse
{
public:
    Parse(cal_fun c) : _cal(c)
    {}
    //处理报文
    std::string Entry(std::string &package)
    {
        std::string message;
        std::string respstr;
        //1. 判断报文完整性 处理多个报文while
        while(Decode(package, &message))
        {
            LOG(LogLevel::DEBUG) << "Content : \n" << message;
            if(message.empty())
                break;
            //2. 反序列化
            Request req;
            if(!req.Deserialize(message))
                break;
            std::cout << "##############" << std::endl;
            req.Print();
            std::cout << "###############" << std::endl;

            //3.计算
            Response resp = _cal(req);
            //4.序列化
            std::string res;
            resp.Serialize(res);
            LOG(LogLevel::DEBUG) << "序列化: \n" << res;

            //5. 添加长度报文字段
            Encode(res);
            LOG(LogLevel::DEBUG) << "Encode :\n" << res;

            //6.拼接应答
            respstr += res;
        }
        LOG(LogLevel::DEBUG) << "respstr:\n" << respstr;
        return respstr;
    }
private:
    cal_fun _cal;
};

int main()
{
    //ENABLE_CONSOLE_LOG();
    //Command cmd;
    // std::unique_ptr<TcpServer> tsvr = std::make_unique<TcpServer>([&cmd](std::string cmdstr)
    //     {
    //         return cmd.Execute(cmdstr);
    //     });
    // tsvr->InitServer();
    // tsvr->Start();

    ENABLE_FILE_LOG();
    Deamon(false, false);

    //1.计算模块
    Calculator mycal;
    //2.解析模块
    Parse myparse([&mycal](const Request &req){
        return mycal.Execute(req);
    });
    //3.通信模块, 只负责IO
    std::unique_ptr<TcpServer> tsvr = std::make_unique<TcpServer>([&myparse](std::string &package)
    {
        return myparse.Entry(package);
    });
    tsvr->InitServer();
    tsvr->Start();
    return 0;
}